﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YJKArch.Utils;

namespace YJKArch.EditFloor
{
	public class PoleEndInterimCreator
	{
		public PoleEndInterimCreator(UIApplication uiApp)
		{
			this.m_uiApplication = uiApp;
			this.m_document = this.m_uiApplication.ActiveUIDocument.Document;
		}

		public List<ThicknessOfEdgeInfo> GetPoleEndInterimListByColumn(bool isZeroThickness)
		{
			new Dictionary<int, List<Wall>>();
			Dictionary<int, List<Wall>> wallListByColumn = new FindWallsByColumnKit(this.m_uiApplication).GetWallListByColumn();
			Autodesk.Revit.DB.View activeView = this.m_uiApplication.ActiveUIDocument.ActiveView;
			List<ThicknessOfEdgeInfo> list = new List<ThicknessOfEdgeInfo>();
			foreach (KeyValuePair<int, List<Wall>> keyValuePair in wallListByColumn)
			{
				BoundingBoxXYZ boundingBoxXYZ = this.m_document.GetElement(new ElementId(keyValuePair.Key)).get_BoundingBox(activeView);
				double num = Common.MMToFeet(50.0);
				new List<CurveLoop>();
				new CurveLoop();
				XYZ xyz = new XYZ(boundingBoxXYZ.Min.X - num, boundingBoxXYZ.Min.Y - num, boundingBoxXYZ.Min.Z);
				XYZ xyz2 = new XYZ(boundingBoxXYZ.Max.X + num, boundingBoxXYZ.Max.Y + num, boundingBoxXYZ.Min.Z);
				XYZ xyz3 = Geometry.CalculatMidPoint(xyz, xyz2);
				double dRadius = xyz.DistanceTo(xyz2) / 1.8;
				List<ThicknessOfEdgeInfo> list2 = new List<ThicknessOfEdgeInfo>();
				foreach (Wall wall in keyValuePair.Value)
				{
					Wall wall2 = wall as Wall;
					double thickness = 0.0;
					if (!isZeroThickness)
					{
						thickness = wall2.Width;
					}
					ThicknessOfEdgeInfo item = new ThicknessOfEdgeInfo((wall2.Location as LocationCurve).Curve, thickness, wall2.Id);
					list2.Add(item);
				}
				list.AddRange(this.GetPoleEndInterim(list2, new XYZ(xyz3.X, xyz3.Y, 0.0), dRadius));
			}
			return list;
		}

		private List<ThicknessOfEdgeInfo> GetPoleEndInterim(List<ThicknessOfEdgeInfo> poleLocationInfos, XYZ ptCenter, double dRadius)
		{
			List<ThicknessOfEdgeInfo> list = new List<ThicknessOfEdgeInfo>();
			List<int> list2 = new List<int>();
			for (int i = 0; i < poleLocationInfos.Count; i++)
			{
				ThicknessOfEdgeInfo thicknessOfEdgeInfo = poleLocationInfos[i];
				double val = thicknessOfEdgeInfo.StartPoint.DistanceTo(ptCenter);
				double num = thicknessOfEdgeInfo.EndPoint.DistanceTo(ptCenter);
				if (Geometry.GreaterThan(val, dRadius * 2.0) && Geometry.GreaterThan(num, dRadius * 2.0))
				{
					list.Add(thicknessOfEdgeInfo);
					poleLocationInfos.RemoveAt(i);
					i--;
				}
				else if (Geometry.LessThan(val, num))
				{
					list2.Add(0);
				}
				else
				{
					list2.Add(1);
				}
			}
			List<ThicknessOfEdgeInfo> result = new List<ThicknessOfEdgeInfo>();
			for (int i = 0; i < poleLocationInfos.Count; i++)
			{
				ThicknessOfEdgeInfo edge = poleLocationInfos[i];
				for (int j = i + 1; j < poleLocationInfos.Count; j++)
				{
					ThicknessOfEdgeInfo edge2 = poleLocationInfos[j];
					this.GetTowPolesEndInterim(edge, list2[i], edge2, list2[j], ptCenter, ref result);
				}
			}
			return result;
		}

		private void GetTowPolesEndInterim(ThicknessOfEdgeInfo edge1, int endIndex1, ThicknessOfEdgeInfo edge2, int endIndex2, XYZ ptCenter, ref List<ThicknessOfEdgeInfo> interims)
		{
			double eps = Common.MMToFeet(5.0);
			double thickness = 0.0;
			XYZ currentPoint = this.GetCurrentPoint(edge1, endIndex1);
			XYZ currentPoint2 = this.GetCurrentPoint(edge2, endIndex2);
			if (edge1.IsArc && edge2.IsArc)
			{
				if (Geometry.IsEqual(edge1.Center.DistanceTo(edge2.Center), 0.0, eps))
				{
					XYZ xyz = Geometry.CalculatMidPoint(currentPoint, currentPoint2);
					if (Geometry.IsEqual(edge1.Radius, edge1.Radius, eps))
					{
						xyz = Geometry.CalculateFootPoint(edge1.StartPoint, edge1.EndPoint, edge1.Center, xyz);
						this.CanBeCreateEdgeInfo(currentPoint, xyz, edge1.Thickness, edge1.HostElementId, ref interims);
						this.CanBeCreateEdgeInfo(currentPoint2, xyz, edge2.Thickness, edge2.HostElementId, ref interims);
						return;
					}
					XYZ xyz2 = Geometry.CalculateFootPoint(edge1.StartPoint, edge1.EndPoint, edge1.Center, xyz);
					XYZ ptEnd = Geometry.CalculateFootPoint(edge2.StartPoint, edge2.EndPoint, edge1.Center, xyz);
					this.CanBeCreateEdgeInfo(currentPoint, xyz2, edge1.Thickness, edge1.HostElementId, ref interims);
					this.CanBeCreateEdgeInfo(currentPoint2, ptEnd, edge2.Thickness, edge2.HostElementId, ref interims);
					this.CanBeCreateEdgeInfo(xyz2, ptEnd, thickness, ElementId.InvalidElementId, ref interims);
					return;
				}
				else
				{
					XYZ ptEnd2 = null;
					if (this.IntersectTowEdges(edge1, edge2, ptCenter, ref ptEnd2))
					{
						this.CanBeCreateEdgeInfo(currentPoint, ptEnd2, edge1.Thickness, edge1.HostElementId, ref interims);
						this.CanBeCreateEdgeInfo(currentPoint2, ptEnd2, edge2.Thickness, edge2.HostElementId, ref interims);
						return;
					}
				}
			}
			else if (!edge1.IsArc && !edge2.IsArc)
			{
				if (Geometry.IsParallel(edge1.Normal, edge2.Normal, 1E-09))
				{
					XYZ xyz3 = Geometry.CalculatMidPoint(currentPoint, currentPoint2);
					if (Geometry.Is_Points_Collinear(edge1.StartPoint, edge1.EndPoint, edge2.StartPoint, 1E-09))
					{
						this.CanBeCreateEdgeInfo(currentPoint, xyz3, edge1.Thickness, edge1.HostElementId, ref interims);
						this.CanBeCreateEdgeInfo(currentPoint2, xyz3, edge2.Thickness, edge2.HostElementId, ref interims);
						return;
					}
					XYZ xyz4 = Geometry.CalculateFootPoint(edge1.StartPoint, edge1.EndPoint, xyz3);
					XYZ ptEnd3 = Geometry.CalculateFootPoint(edge2.StartPoint, edge2.EndPoint, xyz3);
					this.CanBeCreateEdgeInfo(currentPoint, xyz4, edge1.Thickness, edge1.HostElementId, ref interims);
					this.CanBeCreateEdgeInfo(currentPoint2, ptEnd3, edge2.Thickness, edge2.HostElementId, ref interims);
					this.CanBeCreateEdgeInfo(xyz4, ptEnd3, thickness, ElementId.InvalidElementId, ref interims);
					return;
				}
				else
				{
					XYZ ptEnd4 = null;
					if (this.IntersectTowEdges(edge1, edge2, ptCenter, ref ptEnd4))
					{
						this.CanBeCreateEdgeInfo(currentPoint, ptEnd4, edge1.Thickness, edge1.HostElementId, ref interims);
						this.CanBeCreateEdgeInfo(currentPoint2, ptEnd4, edge2.Thickness, edge2.HostElementId, ref interims);
						return;
					}
				}
			}
			else
			{
				XYZ ptEnd5 = null;
				if (this.IntersectTowEdges(edge1, edge2, ptCenter, ref ptEnd5))
				{
					this.CanBeCreateEdgeInfo(currentPoint, ptEnd5, edge1.Thickness, edge1.HostElementId, ref interims);
					this.CanBeCreateEdgeInfo(currentPoint2, ptEnd5, edge2.Thickness, edge2.HostElementId, ref interims);
				}
			}
		}

		private bool IntersectTowEdges(ThicknessOfEdgeInfo edge1, ThicknessOfEdgeInfo edge2, XYZ ptCenter, ref XYZ ptInter)
		{
			Curve curve = edge1.ConvertTo(this.m_uiApplication.Application);
			Curve curve2 = edge2.ConvertTo(this.m_uiApplication.Application);
			XYZ xyz = Geometry.IntersectWithTwoCurves(curve, curve2, ptCenter, true, true, this.m_uiApplication.Application);
			if (xyz != null)
			{
				ptInter = xyz;
				return true;
			}
			return false;
		}

		private XYZ GetCurrentPoint(ThicknessOfEdgeInfo edge, int endIndex)
		{
			if (endIndex == 0)
			{
				return edge.StartPoint;
			}
			return edge.EndPoint;
		}

		private void CanBeCreateEdgeInfo(XYZ ptStart, XYZ ptEnd, double thickness, ElementId hostId, ref List<ThicknessOfEdgeInfo> interims)
		{
			if (Geometry.GreaterThan(ptStart.DistanceTo(ptEnd), 0.0))
			{
				for (int i = 0; i < interims.Count; i++)
				{
					ThicknessOfEdgeInfo thicknessOfEdgeInfo = interims[i];
					XYZ startPoint = null;
					XYZ endPoint = null;
					Geometry.OverlapType overlapType = Geometry.IsOverlapOfTwoLine(ptStart, ptEnd, thicknessOfEdgeInfo.StartPoint, thicknessOfEdgeInfo.EndPoint, ref startPoint, ref endPoint, false, Common.MMToFeet(1.0));
					if (overlapType == Geometry.OverlapType._OT_Equality || overlapType == Geometry.OverlapType._OT_SecondIncludeFirst)
					{
						return;
					}
					if (overlapType == Geometry.OverlapType._OT_FirstIncludeSecond)
					{
						interims[i].StartPoint = ptStart;
						interims[i].EndPoint = ptEnd;
						return;
					}
					if (overlapType == Geometry.OverlapType._OT_Part)
					{
						interims[i].StartPoint = startPoint;
						interims[i].EndPoint = endPoint;
						return;
					}
				}
				ThicknessOfEdgeInfo item = new ThicknessOfEdgeInfo(ptStart, ptEnd, 0.0, thickness, hostId);
				interims.Add(item);
			}
		}

		private UIApplication m_uiApplication;

		protected Autodesk.Revit.DB.Document m_document;

		public enum PoleType
		{
			PT_None,
			PT_Wall,
			PT_Beam
		}
	}
}
